﻿namespace Sai.Core.Introspection
{
	using System;

	public class MethodDeclaration : FunctionMember, IExactlyMatch<MethodDeclaration>, ISourceCodeProvider, ILooselyMatch<MethodDeclaration> 
	{
		public MethodDeclaration(TypeName typeName)
			: base(typeName)
		{
			this.Signature = new Signature();
		}

		public MethodDeclaration(string name, TypeName typeName, ObsoleteMarker obsolete, TypeName declaringType)
			: base(typeName, obsolete, declaringType)
		{
			this.Name = name;
			this.Signature = new Signature();
		}

		public string Name { get; set; }

		public Signature Signature { get; set; }

        public bool IsAbstract { get; set; }

        public bool IsStatic { get; set; }

		// if object in same namespace leave out namespace
		// to string with full namespaces xml doc tags
		// to string for pretty printing
		public override string ToString()
		{
			return string.Format(
							"{0}{1} {2}",
                            this.IsAbstract ? "abstract " : string.Empty,
                            this.TypeName,
							//this.Name,
							this.Signature);
		}

		public bool ExactMatchFor(MethodDeclaration other)
		{
			bool exact = string.Compare(
				this.ToString(),
				other.ToString(),
				StringComparison.Ordinal) == 0;

			return exact;
		}

        public bool Matches(string methodName)
        {
            return string.Compare(
                this.Name,
                methodName,
                StringComparison.Ordinal) == 0;
        }

		public SourceCode ToCode()
		{
            SourceCode code = new SourceCode();

            if (this.IsProtected)
            {
                code.Add(new KeywordTag("protected"));
            }
            else
            {
                code.Add(new KeywordTag("public"));
            }

            if (this.IsAbstract)
            {
                code.Add(new KeywordTag("abstract"));
            }

            code.Add(this.TypeName.ToCode());
            code.Add(new IdentifierTag(this.Name));
            code.Add(new PunctuationTag("("));
            code.Add(this.Signature.ToCode());
            code.Add(new PunctuationTag(")"));

            return code;
        }

        public bool LooseMatchFor(MethodDeclaration other)
        {
            return this.Name == other.Name;
        }
    }
}
